/*
 * Copyright (c) 2010, okazoh_tk. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *  - Neither the name of the copyright holder nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "alkes/gfx/StrokeStyle.h"

#define LINEWIDTH_MASK      (0x000000FF)
#define LINEWIDTH_OFFSET    (0)

#define STARTLINECAP_MASK   (0x0000FF00)
#define STARTLINECAP_OFFSET (8)

#define ENDLINECAP_MASK     (0x00FF0000)
#define ENDLINECAP_OFFSET   (16)

#define LINEJOIN_MASK       (0x0F000000)
#define LINEJOIN_OFFSET     (24)

#define LINESTYLE_MASK      (0xF0000000)
#define LINESTYLE_OFFSET    (28)

#define bits_get(var, mask, offset)         (((var) & (mask)) >> (offset))
#define bits_set(var, value, mask, offset)  do { *(var) = (*(var) & (~(mask))) | (((value) << offset) & (mask)); } while(0)

namespace alkes {

StrokeStyle::StrokeStyle()
: attributes_(0)
, start_linecap_option_(0)
, end_linecap_option_(0)
{
}

StrokeStyle::~StrokeStyle()
{
}

StrokeStyle::StrokeStyle(const StrokeStyle& rh)
: attributes_(rh.attributes_)
, start_linecap_option_(rh.start_linecap_option_)
, end_linecap_option_(rh.end_linecap_option_)
{
}

void StrokeStyle::operator=(const StrokeStyle& rh)
{
    attributes_ = rh.attributes_;
    start_linecap_option_ = rh.start_linecap_option_;
    end_linecap_option_ = rh.end_linecap_option_;
}

void StrokeStyle::setStartLineCap(LineCap linecap, int32_t option)
{
    bits_set(&attributes_, linecap, STARTLINECAP_MASK, STARTLINECAP_OFFSET);
    start_linecap_option_ = option;
}

StrokeStyle::LineCap StrokeStyle::getStartLineCap() const
{
    return (LineCap)bits_get(attributes_, STARTLINECAP_MASK, STARTLINECAP_OFFSET);
}

void StrokeStyle::setEndLineCap(LineCap linecap, int32_t option)
{
    bits_set(&attributes_, linecap, ENDLINECAP_MASK, ENDLINECAP_OFFSET);
    end_linecap_option_ = option;
}

StrokeStyle::LineCap StrokeStyle::getEndLineCap() const
{
    return (LineCap)bits_get(attributes_, ENDLINECAP_MASK, ENDLINECAP_OFFSET);
}

void StrokeStyle::setLineJoin(LineJoin linejoin)
{
    bits_set(&attributes_, linejoin, LINEJOIN_MASK, LINEJOIN_OFFSET);
}

StrokeStyle::LineJoin StrokeStyle::getLineJoin() const
{
    return (LineJoin)bits_get(attributes_, LINEJOIN_MASK, LINEJOIN_OFFSET);
}

void StrokeStyle::setLineStyle(LineStyle linestyle)
{
    bits_set(&attributes_, linestyle, LINESTYLE_MASK, LINESTYLE_OFFSET);
}

StrokeStyle::LineStyle StrokeStyle::getLineStyle() const
{
    return (LineStyle)bits_get(attributes_, LINESTYLE_MASK, LINESTYLE_OFFSET);
}

}
